#ifndef ODBC_AUTO_COMMIT_TRANSACTION_POLICY_HPP
#define ODBC_AUTO_COMMIT_TRANSACTION_POLICY_HPP

#include "odbc/details/os_sql_wrapper.hpp"

namespace odbc
{

/// \ingroup odbcpp
/// \brief It implements a transaction policy that relies on automatic or manual commits.
/// \param AutoCommit it specified whether a commit is executed automatically when the ODBC connection is closed (value 
///		\c true), or that a rollback is executed when the ODBC connection is closed (value \c false).
template< bool AutoCommit = false>
struct auto_commit_transaction_policy
{
	enum { has_auto_commit = AutoCommit };

	/// \brief It initializes configures the connection's transaction policy.
	/// \details This method is called by the connection at initialization time.
	static void setup( SQLHANDLE conn_h)
	{
		check_success(
			SQLSetConnectAttr( conn_h, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)AutoCommit, SQL_IS_UINTEGER),
			conn_h);
	}

	/// \brief It implements the commit logic.
	static void commit( SQLHANDLE conn_h)
	{
		check_success( SQLEndTran( SQL_HANDLE_DBC, conn_h, SQL_COMMIT), conn_h);
	}

	/// \brief It implements the rollback logic.
	/// \details In case of autocommit, the code from this method is (or should be) optimized away, since it will never 
	///		be executed (the condition doesn't change at runtime and it will always be false).
	static void rollback( SQLHANDLE conn_h)
	{
		check_success( SQLEndTran( SQL_HANDLE_DBC, conn_h, SQL_ROLLBACK), conn_h);
	}

private:
	static void check_success( SQLRETURN sql_ret, SQLHANDLE handle)
	{
		if( sql_ret != SQL_SUCCESS && sql_ret != SQL_SUCCESS_WITH_INFO)
		{
			throw odbc_error( sql_ret, handle, SQL_HANDLE_DBC);
		}
	}
};


} // namespace odbc

#endif // ODBC_AUTO_COMMIT_TRANSACTION_POLICY_HPP
